
import sys
sys.path.append(r"c:\Users\14159\Desktop\test_code\hewei\maddpg_-uav\MADDPG-master")

import torch
import numpy as np
import pandas as pd
from runner import Runner
from common.arguments import get_args
from common.utils import make_encirclement_env  # 导入正确的环境创建函数
import os




def evaluate_saved_models():
    """评估已保存的模型获取完成率数据"""
    
    # 获取参数
    args = get_args()
    args.evaluate = True
    args.evaluate_episodes = 100  # 增加评估回合数以获得更准确的完成率
    
    # 使用正确的方式初始化环境
    env, args = make_encirclement_env(args)
    
    # 误码率列表
    ber_values = np.logspace(-3, -2, 10)
    
    results = []
    model_base_path = r"c:\Users\14159\Desktop\test_code\hewei\results_20250701_094606"
    
    for ber in ber_values:
        model_path = os.path.join(model_base_path, f"model_ber_{ber:.6f}")
        
        if os.path.exists(model_path):
            print(f"\n评估误码率 {ber:.6f} 的模型...")
            
            # 创建runner
            runner = Runner(args, env)
            runner.bit_flip_probability = ber
            
            # 加载模型
            try:
                for j, agent in enumerate(runner.agents):
                    actor_path = os.path.join(model_path, f"actor_agent_{j}.pth")
                    critic_path = os.path.join(model_path, f"critic_agent_{j}.pth")
                    
                    if os.path.exists(actor_path) and os.path.exists(critic_path):
                        agent.policy.actor_network.load_state_dict(torch.load(actor_path))
                        agent.policy.critic_network.load_state_dict(torch.load(critic_path))
                        print(f"已加载智能体 {j} 的模型")
                
                # 评估模型 - 修复返回值处理
                avg_return, eval_success_rate = runner.evaluate()  # 正确解包元组
                
                # 手动计算成功率（可以选择使用evaluate返回的成功率或手动计算的成功率）
                success_count = 0
                total_episodes = args.evaluate_episodes
                
                for episode in range(total_episodes):
                    env.reset()
                    step = 0
                    episode_success = False
                    
                    while step < args.evaluate_episode_len:
                        # 收集所有无人机的状态和动作
                        for uav_id, (uav, agent) in enumerate(zip(env.uavs, runner.agents)):
                            # 获取当前状态
                            state = runner.build_state(uav_id)
                            
                            # 选择动作（评估时不使用随机探索）
                            action, _ = agent.select_action(state, epsilon=0.0, uav=uav)
                            
                            # 执行动作
                            reward = env.perform_action(uav, action, step, args.evaluate_episode_len, episode, use_optimized=True)
                        
                        # 检查是否成功合围
                        if env.check_encirclement():
                            episode_success = True
                            break
                        
                        step += 1
                    
                    if episode_success:
                        success_count += 1
                
                # 使用evaluate方法返回的成功率，或者使用手动计算的成功率
                success_rate = eval_success_rate  # 或者使用 success_count / total_episodes
                
                results.append({
                    'ber': ber,
                    'avg_return': avg_return,  # 现在是数值而不是元组
                    'success_rate': success_rate,
                    'training_episodes': 2000
                })
                
                print(f"误码率 {ber:.6f}: 平均回报={avg_return:.2f}, 完成率={success_rate:.3f}")
                
            except Exception as e:
                print(f"加载或评估模型时出错: {e}")
        else:
            print(f"找不到误码率 {ber:.6f} 的模型路径: {model_path}")
    
    # 保存结果
    if results:
        df = pd.DataFrame(results)
        output_path = "evaluation_results_with_completion_rate.xlsx"
        df.to_excel(output_path, index=False)
        print(f"\n评估结果已保存到: {output_path}")
        
        # 调用绘图函数
        plot_completion_rate_from_results(results)
    else:
        print("没有成功评估任何模型")

def plot_completion_rate_from_results(results):
    """从评估结果绘制完成率图表"""
    import matplotlib.pyplot as plt
    from datetime import datetime
    
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    # 提取数据
    ber_values = [r['ber'] for r in results]
    avg_returns = [r['avg_return'] for r in results]
    success_rates = [r['success_rate'] for r in results]
    
    # 创建图表
    plt.figure(figsize=(15, 10))
    
    # 子图1：误码率 vs 完成率（对数坐标）
    plt.subplot(2, 3, 1)
    plt.semilogx(ber_values, success_rates, 'bo-', linewidth=2, markersize=8)
    plt.xlabel('误码率 (BER)')
    plt.ylabel('完成率 (Success Rate)')
    plt.title('误码率对完成率的影响（对数坐标）')
    plt.grid(True, alpha=0.3)
    plt.ylim(0, 1.05)
    
    # 子图2：误码率 vs 完成率（线性坐标）
    plt.subplot(2, 3, 2)
    plt.plot(ber_values, success_rates, 'ro-', linewidth=2, markersize=8)
    plt.xlabel('误码率 (BER)')
    plt.ylabel('完成率 (Success Rate)')
    plt.title('误码率对完成率的影响（线性坐标）')
    plt.grid(True, alpha=0.3)
    plt.ylim(0, 1.05)
    
    # 子图3：误码率 vs 平均回报
    plt.subplot(2, 3, 3)
    plt.semilogx(ber_values, avg_returns, 'go-', linewidth=2, markersize=8)
    plt.xlabel('误码率 (BER)')
    plt.ylabel('平均回报')
    plt.title('误码率对平均回报的影响')
    plt.grid(True, alpha=0.3)
    
    # 子图4：完成率下降百分比
    max_success_rate = max(success_rates)
    completion_degradation = [(max_success_rate - rate) / max_success_rate * 100 for rate in success_rates]
    
    plt.subplot(2, 3, 4)
    plt.semilogx(ber_values, completion_degradation, 'mo-', linewidth=2, markersize=8)
    plt.xlabel('误码率 (BER)')
    plt.ylabel('完成率下降百分比 (%)')
    plt.title('相对于最佳完成率的下降程度')
    plt.grid(True, alpha=0.3)
    
    # 子图5：双轴图：同时显示完成率和平均回报
    plt.subplot(2, 3, 5)
    ax1 = plt.gca()
    color = 'tab:red'
    ax1.set_xlabel('误码率 (BER)')
    ax1.set_ylabel('完成率', color=color)
    line1 = ax1.semilogx(ber_values, success_rates, 'o-', color=color, linewidth=2, markersize=8)
    ax1.tick_params(axis='y', labelcolor=color)
    ax1.set_ylim(0, 1.05)
    
    ax2 = ax1.twinx()
    color = 'tab:blue'
    ax2.set_ylabel('平均回报', color=color)
    line2 = ax2.semilogx(ber_values, avg_returns, 's-', color=color, linewidth=2, markersize=8)
    ax2.tick_params(axis='y', labelcolor=color)
    
    plt.title('误码率对完成率和回报的综合影响')
    ax1.grid(True, alpha=0.3)
    
    # 子图6：数据表格
    plt.subplot(2, 3, 6)
    plt.axis('tight')
    plt.axis('off')
    
    # 创建表格数据
    table_data = []
    for i in range(len(ber_values)):
        table_data.append([
            f"{ber_values[i]:.6f}",
            f"{success_rates[i]:.3f}",
            f"{avg_returns[i]:.2f}",
            f"{completion_degradation[i]:.1f}%"
        ])
    
    table = plt.table(cellText=table_data,
                     colLabels=['误码率', '完成率', '平均回报', '完成率下降'],
                     cellLoc='center',
                     loc='center')
    table.auto_set_font_size(False)
    table.set_fontsize(8)
    table.scale(1.2, 1.5)
    plt.title('详细结果表格')
    
    plt.tight_layout()
    
    # 保存图表
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    plot_path = f"completion_rate_analysis_{timestamp}.png"
    plt.savefig(plot_path, dpi=300, bbox_inches='tight')
    plt.show()
    
    print(f"\n完成率分析图表已保存到: {plot_path}")
    
    # 打印统计信息
    print(f"\n=== 完成率统计分析 ===")
    print(f"误码率范围: {min(ber_values):.6f} - {max(ber_values):.6f}")
    print(f"完成率范围: {min(success_rates):.3f} - {max(success_rates):.3f}")
    print(f"平均完成率: {np.mean(success_rates):.3f}")
    print(f"完成率标准差: {np.std(success_rates):.3f}")
    print(f"最大完成率下降: {max(completion_degradation):.1f}%")

if __name__ == "__main__":
    evaluate_saved_models()
